package tests;

import org.junit.Assert;
import org.junit.Test;

import utils.CustomRandom;
import AlgoritmosGeneticos.model.AlgoritmoGenetico;
import AlgoritmosGeneticos.model.CondicionCorte;
import AlgoritmosGeneticos.model.EstrategiaDeSeleccion;
import AlgoritmosGeneticos.model.OperadorCruce;
import AlgoritmosGeneticos.model.OperadorMutacion;
import AlgoritmosGeneticos.model.Poblacion;
import AlgoritmosGeneticos.model.PoblacionSeleccionada;
import AlgoritmosGeneticos.model.impl.PoblacionImpl;
import AlgoritmosGeneticos.model.impl.corte.CorteContenido;
import AlgoritmosGeneticos.model.impl.corte.CorteEntornoOptimo;
import AlgoritmosGeneticos.model.impl.corte.CorteEstructura;
import AlgoritmosGeneticos.model.impl.corte.CorteIteraciones;
import AlgoritmosGeneticos.model.impl.cruces.CruceSimple;
import AlgoritmosGeneticos.model.impl.mutuaciones.MutacionBasica;
import AlgoritmosGeneticos.model.impl.selecciones.Elite;
import AlgoritmosGeneticos.model.impl.selecciones.Ruleta;

public class TestCortes {
	
	/** 
	 * CORTE POR ITERACIONES 
	 * ----------------------
	 * Corte mas simple por cantidad de iteraciones
	 */
	
	@Test
	public void CorteIteraciones(){
		final int ITERACIONES=30;
		int it=0;
		CondicionCorte condicion = new CorteIteraciones(ITERACIONES);
		condicion.setMaxIterations(100);
		
		while(condicion.seCumple(null)){
			it++;
		}
		System.out.println("CORTE ITERACIONES");
		Assert.assertTrue(it==ITERACIONES);
	}
	
	
	/**
	 * CORTE POR ESTRUCTURA:
	 * --------------------- 
	 * Si algun individuo de la población representa 
	 * el 20 % de la población corta
	 */
	
	@Test
	public void CorteEstructura() throws InterruptedException{
		
		int 	popSize	= 200;
		int 	k		= 20;
		double 	pMut	= 0.01;

		new CustomRandom(1);
		
		OperadorMutacion 		opMut = new MutacionBasica();
		OperadorCruce 			opCru = new CruceSimple();
		EstrategiaDeSeleccion 	estrategiaSeleccion = new Elite();
		EstrategiaDeSeleccion	estrategiaRemplazo = new Ruleta();
		CondicionCorte			condicion = new CorteEstructura(0.7);
		Poblacion 				p= new PoblacionImpl(popSize, k, pMut, AlgoritmoGenetico.fitness.MAXIMO);
		condicion.setMaxIterations(100);
		
		while(condicion.seCumple(p)){
			PoblacionSeleccionada pobSel = p.seleccionar(estrategiaSeleccion);
			pobSel.cruzar(opCru);
			pobSel.mutar(opMut);
			p.reemplazar(pobSel, estrategiaRemplazo);
		}
		
		System.out.println("CORTE ESTRUCURA");
		((CorteEstructura)condicion).verificaPoblacion(p, true);

	}

	/**
	 * ENTORNO AL OPTIMO
	 * ------------------
	 * Considera al más apto: 0.1470947265625
	 * con un entorno 0.0001
	 */
	@Test
	public void CorteEntornoOptimo() throws InterruptedException{
		
		int 	popSize	= 200;
		int 	k		= 20;
		double 	pMut	= 0.01;

		new CustomRandom(1);
		
		OperadorMutacion 		opMut = new MutacionBasica();
		OperadorCruce 			opCru = new CruceSimple();
		EstrategiaDeSeleccion 	estrategiaSeleccion = new Elite();
		EstrategiaDeSeleccion	estrategiaRemplazo = new Ruleta();
		CondicionCorte			condicion = new CorteEntornoOptimo(4.85891275076829, 0.0001);
		Poblacion 				p= new PoblacionImpl(popSize, k, pMut, AlgoritmoGenetico.fitness.MAXIMO);
		condicion.setMaxIterations(100);
		int it=0;
		while(condicion.seCumple(p)){
			PoblacionSeleccionada pobSel = p.seleccionar(estrategiaSeleccion);
			pobSel.cruzar(opCru);
			pobSel.mutar(opMut);
			p.reemplazar(pobSel, estrategiaRemplazo);
			it++;
		}
		System.out.println("CORTE ENTORNO OPTIMO");
		System.out.println( "Iteraciones: " + it );
	}
	
	/**
	 * CORTE POR CONTENIDO
	 * -------------------
	 * Se espera que la poblacion vaya incrementando su 
	 * individuo mas apto en un facto de un 1 % en relacion al 
	 * ultimo individuo más apto, en lapsos de 5 iteraciones.
	 * 
	 */
	
	@Test
	public void CorteContenido() throws InterruptedException{
		
		int 	popSize	= 200;
		int 	k		= 20;
		double 	pMut	= 0.01;

		new CustomRandom(1);
		
		OperadorMutacion 		opMut = new MutacionBasica();
		OperadorCruce 			opCru = new CruceSimple();
		EstrategiaDeSeleccion 	estrategiaSeleccion = new Elite();
		EstrategiaDeSeleccion	estrategiaRemplazo = new Ruleta();
		CondicionCorte			condicion = new CorteContenido(5, 0.01);
		Poblacion 				p= new PoblacionImpl(popSize, k, pMut, AlgoritmoGenetico.fitness.MAXIMO);
		condicion.setMaxIterations(100);
		int it=0;
		while(condicion.seCumple(p)){
			PoblacionSeleccionada pobSel = p.seleccionar(estrategiaSeleccion);
			pobSel.cruzar(opCru);
			pobSel.mutar(opMut);
			p.reemplazar(pobSel, estrategiaRemplazo);
			it++;
		}
		System.out.println("CORTE CONTENIDO");
		System.out.println( "Iteraciones: " + it );
	}


}
